package com.zkh.myframe.core;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Map;

import com.zkh.myframe.database.mapper.MapperEntity;
import com.zkh.myframe.database.mapper.MapperParseException;
import com.zkh.myframe.database.mapper.parser.Parser;
import com.zkh.myutils.io.log.Logger;
import com.zkh.myutils.markup.Element;
import com.zkh.myutils.markup.MarkupException;
import com.zkh.myutils.markup.MarkupParser;
import com.zkh.myutils.utils.Assert;
import com.zkh.myutils.utils.StringUtils;

/**
 * Mapper解析器
 * @author zkh
 */
public class MapperParser {
	
	/**
	 * 解析一个Mapper.xml文件流
	 */
	public static void parseMapper(File file) {
		//读取流
		try(InputStream inputStream = Files.newInputStream(file.toPath())) {
			//解析流
			parseMapper(inputStream, file.getName());
		} catch (IOException e) {
			Logger.error(e);
		}
	}
	
	/**
	 * 解析一个Mapper.xml文件流
	 * @param inputStream Mapper文件流
	 * @param filename 文件名
	 */
	public static void parseMapper(InputStream inputStream, String filename) {
		try {
			//解析Mapper文件
			Element root = MarkupParser.parseInputStream(inputStream);
			//命名空间
			String namespace = root.getAttr("namespace");
			//命名空间为空
			if(StringUtils.isEmpty(namespace)) {
				throw new MapperParseException(filename + "的命名空间不能为空");
			}
			//配置
			Map<String, MapperEntity> map = FrameConfigure.getMapperMap();
			//已存在
			if(map.containsKey(namespace)) {
				throw new MapperParseException(filename + "的命名空间已存在");
			}
			try {
				//创建Mapper
				MapperEntity mapper = new MapperEntity();
				//保存Mapper
				map.put(namespace, mapper);
				//填充Mapper
				Parser.renderMapper(root, namespace, mapper);
			}catch(MapperParseException e) {
				Logger.error(e);
				throw new MapperParseException(filename + "：" + e.getMessage(), e);
			}
		} catch(MarkupException e) {
			throw new MapperParseException(filename + "文件解析失败", e);
		}
	}

	/**
	 * 加载所有指定目录下的所有Mapper
	 * @param path 指定目录
	 */
	static void loadAllMapper(String path) {
		//当前目录File对象
		File file = new File(path);
		//获取目录下所有文件名
		Assert.doIfNotEmpty(file.list(), filenames->{
			//遍历
			for(String filename: filenames) {
				File f = new File(file, filename);
				//目录
				if(f.isDirectory()) {
					loadAllMapper(path + File.separator + filename);
				}else if(filename.endsWith("Mapper.xml")){
					//加载XML，没有则不执行任何操作
					MapperParser.parseMapper(f);
				}
			}
		});
	}
}
